﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Single.AppCore;
using Single.Core.Service;
using Single.Logger;
using System.Diagnostics;
using System.Text;

namespace Single.WebApp.Components
{
    [Authorize(AuthenticationSchemes = AuthScheme)]
    public class WorkController : Controller
    {
        public const string AuthScheme = "work";

        private string areaName;
        private string controllerName;
        private string actionName;

        public bool IsAuthenticated => HttpContext.User.Identity.IsAuthenticated;
        public long UserId => HttpContext.User.GetUserId();
        public string Name => HttpContext.User.GetName();
        public string UserName => HttpContext.User.GetUserName();
        public string Avatar => HttpContext.User.GetAvatar();
        public DateTime PwdTime => HttpContext.User.GetPwdTime();
        public bool IsSuper => HttpContext.User.GetIsSuper();

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            LoggerHelper.Request(context.HttpContext);

            Thread.Sleep(500);

            if (VerifyPower(context))
            {
                IndexUserInfoInit();
                RouteInfoInit(context);
                PageFuncsInit(context);
            }

            base.OnActionExecuting(context);
        }

        private bool VerifyPower(ActionExecutingContext context)
        {
            var path = context.HttpContext.Request.Path.Value?.ToLower();

            var bit = ServiceSysProps.SysRoleMenuFunction.VerifyPower(UserId, path, IsSuper);

            if (!bit)
            {
                context.Result = Content(ServiceResult.Serialize(false, "权限不足", path));
            }

            return bit;
        }

        private void IndexUserInfoInit()
        {
            ViewBag.UserId = UserId;
            ViewBag.UserName = UserName;
            ViewBag.Name = Name;
            ViewBag.Avatar = Avatar;
            ViewBag.PwdIsExpire = ServiceSysProps.SysUser.PasswordIsExpire(PwdTime).Success;
        }

        private void RouteInfoInit(ActionExecutingContext context)
        {
            var routeValues = context.RouteData.Values;

            areaName = routeValues["area"].ToString().ToLower();
            controllerName = routeValues["controller"].ToString().ToLower();
            actionName = routeValues["action"].ToString().ToLower();

            ViewBag.PageName = GetName(string.Empty);
            ViewBag.PageTemplate = GetTemplate(string.Empty);
            ViewBag.PagePath = $"/{areaName}/{controllerName}";

            ViewBag.GetCompName = new Func<string, string>(GetName);
            ViewBag.GetCompTemplate = new Func<string, string>(GetTemplate);
        }

        private string GetName(string module)
        {
            if (!string.IsNullOrEmpty(module))
            {
                module = $"_{module}";
            }

            return $"{areaName}_{controllerName}_{actionName}{module}";
        }

        private string GetTemplate(string module)
        {
            if (!string.IsNullOrEmpty(module))
            {
                module = $"_{module}";
            }

            return $"{areaName}_{controllerName}_{actionName}{module}_template";
        }

        private void PageFuncsInit(ActionExecutingContext context)
        {
            var pageFuncs = new Dictionary<string, string>();

            if (RequestUtility.QueryValue(context.HttpContext, "_mid", out long menuid))
            {
                var fs = ServiceSysProps.SysMenuFunction.GetByUserId(menuid, UserId, IsSuper);

                var gfs = fs.GroupBy(m => m.Type).ToList();

                gfs.ForEach(m =>
                {
                    var sb = new StringBuilder();

                    foreach (var item in m)
                    {
                        sb.Append($"<el-button icon=\"{item.Icon}\" v-on:click=\"{item.Value}\" {item.Attrs}>{item.Title}</el-button>");
                    }

                    pageFuncs.Add($"{m.Key}", sb.ToString());
                    pageFuncs.Add($"{m.Key}:count", m.Count(n => string.IsNullOrEmpty(n.Attrs) || !n.Attrs.Contains("v-else")).ToString());
                });
            }

            ViewBag.PageFuncDic = pageFuncs;
            ViewBag.PageFuncs = new Func<string, string>(PageFuncs);
            ViewBag.MenuId = menuid;
            ViewBag.MenuChildId = new Func<long, string, string>(PageChildMid);
        }

        private string PageFuncs(string key)
        {
            if (ViewBag.PageFuncDic != null)
            {
                if (ViewBag.PageFuncDic.ContainsKey(key))
                {
                    return ViewBag.PageFuncDic[key];
                }
            }

            return string.Empty;
        }

        private string PageChildMid(long menuid, string src)
        {
            var child = ServiceSysProps.SysMenuFunction.GetChildByUserId(menuid, src, UserId, IsSuper);

            return child?.MenuId.ToString() ?? string.Empty;
        }

        /// <summary>
        /// 根据数据范围分类获取数据范围
        /// null:用户拥有全部数据权限
        /// [xx,xx]:用户拥有部分组织的权限
        /// []：用户仅自己权限
        /// </summary>
        /// <returns></returns>
        protected List<long> GetUserDataScope()
        {
            //组织id集合
            var list = new List<long>();

            var roleList = ServiceSysProps.SysUserRole.GetByUserId(UserId);

            if (roleList.FirstOrDefault(m => m.SysRole.DataScope == "所有组织") != null)
            {
                return null;
            }

            if (roleList.FirstOrDefault(m => m.SysRole.DataScope == "仅所属组织") != null)
            {
                var user = ServiceSysProps.SysUser.Get(UserId);

                if (user != null) { list.Add(user.OrgId); }
            }

            if (roleList.FirstOrDefault(m => m.SysRole.DataScope == "所属组织及以下") != null)
            {
                var user = ServiceSysProps.SysUser.Get(UserId);

                if (user != null)
                {
                    var orgList = ServiceSysProps.SysOrg.GetSelfAndChildOrgList(user.OrgId);

                    list.AddRange(orgList.Select(m => m.Id).Distinct());
                }
            }

            if (roleList.FirstOrDefault(m => m.SysRole.DataScope == "指定组织") != null)
            {
                var roleIds = roleList.Where(m => m.SysRole.DataScope == "指定组织").Select(m => m.RoleId).ToList();

                var orgList = ServiceSysProps.SysRoleDefineOrg.GetByRoleIds(roleIds);

                list.AddRange(orgList.Select(m => m.OrgId).Distinct());
            }

            return list;
        }
    }
}